﻿using System;
using System.Linq;
using System.Threading;
using ActionLogic.Impl.Enum;
using ActionLogic.Interface;
using Wintellect.PowerCollections;

namespace ActionLogic.Impl
{
    public class ActionExecutor : IActionExecutor
    {
        private static ActionExecutor _instance = new ActionExecutor();

        private OrderedMultiDictionary<double, Action> _actionQueue;

        public State State { get; private set; }

        public void Pause()
        {
            State = State.PAUSE;
        }

        public void Stop()
        {
            State = State.STOP;
            lock (this)
            {
                _actionQueue.Clear();
            }
        }

        public void Run()
        {
            State = State.RUN;

            while (State.RUN == State)
            {
                lock (this)
                {
                    Execute();
                }
            }
        }

        private ActionExecutor()
        {
            _actionQueue = new OrderedMultiDictionary<double, Action>(true);
            State = State.STOP;
        }

        public static IActionExecutor GetInstance()
        {
            return _instance;
        }

        public void Add(double priority, ExecuteFunc task)
        {
            _actionQueue.Add(priority, new Action(task));
        }

        public void Execute()
        {
            if (State != State.RUN)
            {
                return;
            }

            if (IsEmpty())
            {
                throw new Exception("Empty ActionQueue. Mb use Run after use Stop?");
            }

            var min = _actionQueue.Keys.Min();
            var actions = _actionQueue[min];
            for (int i = 0; i < actions.Count; i++)
            {

                actions.ElementAt(i).Execute();

            }

            _actionQueue.Remove(min);
        }

        /*
        public bool ExecutionAllowed()
        {
            var minAllowed = _restrictions.Values.Min();
            var min = _actionQueue.Keys.Min();

            return min <= minAllowed;
        }
        */

        public bool IsEmpty()
        {
            return _actionQueue.Count == 0;
        }
    }
}
